#ifndef VSqlFields_H
#define VSqlFields_H					 

#include "VPropEditor.h"

///////////////////////////////////////////////////////////////////////////////
class VSqlFields;
typedef QSharedPointer<VSqlFields> VSqlFieldsPtr;
class VSqlField;
typedef QSharedPointer<VSqlField> VSqlFieldPtr;
///////////////////////////////////////////////////////////////////////////////

class VSqlFieldType
{
public:
	enum EType 
	{
		EType_idAuto		= 1,
		EType_string		= 2,
		EType_listId		= 3,
		EType_refId			= 4,
		EType_id				= 5,
		EType_integer		= 6,
		EType_dateTime	= 7,
		EType_table			= 8,
		EType_refString	= 9,
		EType_text			= 10,
	};

	static VSqlFieldType maps;

public:
	VSqlFieldType();

	QString eTypeToDisplayName(EType eType) const;

	QStringList toStringList() const;
	EType posToEType(int pos) const;
	int eTypeToPos(EType eType) const;

private:
	typedef QHash<EType,QString> VTypeToDisplayName;
	VTypeToDisplayName m_typeToDisplayName;

	typedef QList<EType> VPosToType;
	VPosToType m_posToType;
};

///////////////////////////////////////////////////////////////////////////////

class VSqlFieldInfo
{
public:
	VSqlFieldInfo();

	void setUnicode(const QString &v) { m_unicode = v;}
	QString unicode() const { return m_unicode;}

	void setCreateDT(const QDateTime &v) { m_createDT = v;}
	QDateTime createDT() const { return m_createDT;}

	void setAutor(const QString &v) { m_autor = v;}
	QString autor() const { return m_autor;}

	void setComment(const QString &v) { m_comment = v;}
	QString comment() const { return m_comment;}

public:
	void select(const QString &tableName);

private:
	QString m_unicode;
	QDateTime m_createDT;
	QString m_autor;
	QString m_comment;
	bool m_tableInfoIsSelect;
};

///////////////////////////////////////////////////////////////////////////////

class VSqlField : public QObject
{
	Q_OBJECT

	static const QString propName() { return "name";}
	//Q_PROPERTY(QString name READ name WRITE setName);// NOTIFY nameChanged);

public:
	void setName(const QString &v) { m_name = v;}
	QString name() const { return m_name;}

	//void setUnicode(const QString &v) { m_unicode = v;}
	QString unicode() const { return m_unicode;}

	void setCreateDT(const QDateTime &v) { m_createDT = v;}
	QDateTime createDT() const { return m_createDT;}
	
	void setAutor(const QString &v) { m_autor = v;}
	QString autor() const { return m_autor;}
	
	void setComment(const QString &v) { m_comment = v;}
	QString comment() const { return m_comment;}

public:	
	virtual bool isRef() const { return false;}
	virtual VSqlFieldType::EType eType() const = 0;
	virtual QString sqlType() const = 0;
	virtual VSqlFieldPtr clone() const = 0;

	virtual void toRecord(QSqlRecord &record) const;
	virtual void fromRecord(const QSqlRecord &record);
	
	virtual QWidget *factoryValueEditor(QWidget *parent) const = 0;
	virtual void factoryPropertyEditor(VPropEditor *propEditor) const;

//signals:
//	void nameChanged();

protected:
	void copyFrom(const VSqlField *from);
	
private:
	QString m_name;
	QString m_unicode;
	QDateTime m_createDT;
	QString m_autor;
	QString m_comment;
};

///////////////////////////////////////////////////////////////////////////////

class VSqlFields : public QList<VSqlFieldPtr>
{
public:
	static VSqlFieldPtr factoryField(VSqlFieldType::EType fieldType);

public:
	~VSqlFields() {}

	void append(const VSqlFieldPtr &field);
	void append(const VSqlField &field);
	
	VSqlFieldPtr findFieldByName(const QString &fieldName) const;
	VSqlFieldPtr findFieldByEType(VSqlFieldType::EType eType) const;

	void toRecords(QList<QSqlRecord> &records) const;
	void fromRecords(const QList<QSqlRecord> &records);

	QSqlRecord record() const;
	QString sqlFieldsName() const;

	void addWidgetsTo(QWidget *parent,QFormLayout *layout) const;
	
public:
	void createTable(const QString &tableName) const;
};

///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////

class VSqlRegTables
{
public:
	static const QString tName()				{ return "VRegTables";}

	static const QString fUnicode()			{ return "fUnicode";}
	static const QString fTableName()		{ return "fTableName";}
	static const QString fFieldName()		{ return "fFieldName";}
	static const QString fFieldType()		{ return "fFieldType";}

	static const QString fCreateDT()		{ return "fCreateDT";}
	static const QString fAutor()				{ return "fAutor";}
	static const QString fComment()			{ return "fComment";}

	static const QString fFieldLength()	{ return "fFieldLength";}
	static const QString fToTableName()	{ return "fToTableName";}
	static const QString fToFieldName()	{ return "fToFieldName";}

	static bool isCreate();

	static VSqlFields fields();
	static QSqlRecord record() { return fields().record();}
	static QString sqlFieldsName() { return fields().sqlFieldsName();}

public:
	static const QString listId() { return "_listId";}

public:
	static void create() { fields().createTable(tName());}
	static void thisRegisterInDb() { insertFields(tName(),fields());}

	static QList<QSqlRecord> recordsFrom(QSqlQuery &query);

	static QSqlQuery selectTablesAsQuery();

	static QSqlQuery selectTableAsQuery(const QVariant &tableName);

	static QSqlQuery selectFieldsAsQuery(const QVariant &tableName);
	static QList<QSqlRecord> selectFieldsAsRecords(const QVariant &tableName);
	static VSqlFields selectFieldsAsFields(const QVariant &tableName);

	static void insertFields(const QString &tableName,const VSqlFields &insFields);

private:
	static void insertRecords(const QList<QSqlRecord> &records);
};

///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////

class VSqlFieldIdAuto : public VSqlField
{
	Q_OBJECT

public:
	VSqlFieldIdAuto &setName(const QString &v) { VSqlField::setName(v); return *this;}
	VSqlFieldIdAuto &setCreateDT(const QDateTime &v) { VSqlField::setCreateDT(v); return *this;}
	VSqlFieldIdAuto &setAutor(const QString &v) { VSqlField::setAutor(v); return *this;}
	VSqlFieldIdAuto &setComment(const QString &v) { VSqlField::setComment(v); return *this;}

	virtual QString sqlType() const { return "bigint not null";}
	virtual VSqlFieldType::EType eType() const { return VSqlFieldType::EType_idAuto;}
	virtual VSqlFieldPtr clone() const;

	virtual QWidget *factoryValueEditor(QWidget *parent) const;
};

typedef QSharedPointer<VSqlFieldIdAuto> VSqlFieldIdAutoPtr;

///////////////////////////////////////////////////////////////////////////////

class VSqlFieldId : public VSqlField
{
	Q_OBJECT

public:
	VSqlFieldId &setName(const QString &v) { VSqlField::setName(v); return *this;}
	VSqlFieldId &setCreateDT(const QDateTime &v) { VSqlField::setCreateDT(v); return *this;}
	VSqlFieldId &setAutor(const QString &v) { VSqlField::setAutor(v); return *this;}
	VSqlFieldId &setComment(const QString &v) { VSqlField::setComment(v); return *this;}

	virtual QString sqlType() const { return "bigint";}
	virtual VSqlFieldType::EType eType() const { return VSqlFieldType::EType_id;}
	virtual VSqlFieldPtr clone() const;

	virtual QWidget *factoryValueEditor(QWidget *parent) const;
};

typedef QSharedPointer<VSqlFieldId> VSqlFieldIdPtr;

///////////////////////////////////////////////////////////////////////////////

class VSqlFieldString : public VSqlField
{
	Q_OBJECT

public:
	VSqlFieldString() { m_maxLength = 100;}
	
	VSqlFieldString &setName(const QString &v) { VSqlField::setName(v); return *this;}
	VSqlFieldString &setCreateDT(const QDateTime &v) { VSqlField::setCreateDT(v); return *this;}
	VSqlFieldString &setAutor(const QString &v) { VSqlField::setAutor(v); return *this;}
	VSqlFieldString &setComment(const QString &v) { VSqlField::setComment(v); return *this;}

	VSqlFieldString &setMaxLength(int v) { m_maxLength = v; return *this;}
	int maxLength() const { return m_maxLength;}
	
	virtual QString sqlType() const { return QString("varchar(%1)").arg(m_maxLength);}
	virtual VSqlFieldType::EType eType() const { return VSqlFieldType::EType_string;}
	virtual VSqlFieldPtr clone() const;

	virtual void toRecord(QSqlRecord &record) const;
	virtual void fromRecord(const QSqlRecord &record);

	virtual QWidget *factoryValueEditor(QWidget *parent) const;
	virtual void factoryPropertyEditor(VPropEditor *propEditor) const;
	
private:
	int m_maxLength;
};

typedef QSharedPointer<VSqlFieldString> VSqlFieldStringPtr;

///////////////////////////////////////////////////////////////////////////////

class VSqlFieldInteger : public VSqlField
{
	Q_OBJECT

public:
	VSqlFieldInteger() {}

	VSqlFieldInteger &setName(const QString &v) { VSqlField::setName(v); return *this;}
	VSqlFieldInteger &setCreateDT(const QDateTime &v) { VSqlField::setCreateDT(v); return *this;}
	VSqlFieldInteger &setAutor(const QString &v) { VSqlField::setAutor(v); return *this;}
	VSqlFieldInteger &setComment(const QString &v) { VSqlField::setComment(v); return *this;}

	virtual QString sqlType() const { return QString("integer");}
	virtual VSqlFieldType::EType eType() const { return VSqlFieldType::EType_integer;}
	virtual VSqlFieldPtr clone() const;

	virtual QWidget *factoryValueEditor(QWidget *parent) const;
};

typedef QSharedPointer<VSqlFieldInteger> VSqlFieldIntegerPtr;

///////////////////////////////////////////////////////////////////////////////

class VSqlFieldText : public VSqlField
{
	Q_OBJECT

public:
	VSqlFieldText() {}

	VSqlFieldText &setName(const QString &v) { VSqlField::setName(v); return *this;}
	VSqlFieldText &setCreateDT(const QDateTime &v) { VSqlField::setCreateDT(v); return *this;}
	VSqlFieldText &setAutor(const QString &v) { VSqlField::setAutor(v); return *this;}
	VSqlFieldText &setComment(const QString &v) { VSqlField::setComment(v); return *this;}

	virtual QString sqlType() const { return QString("blob sub_type 1");}
	virtual VSqlFieldType::EType eType() const { return VSqlFieldType::EType_text;}
	virtual VSqlFieldPtr clone() const;

	virtual QWidget *factoryValueEditor(QWidget *parent) const;
};

typedef QSharedPointer<VSqlFieldText> VSqlFieldTextPtr;

///////////////////////////////////////////////////////////////////////////////

class VSqlFieldDateTime : public VSqlField
{
	Q_OBJECT

public:
	VSqlFieldDateTime() {}

	VSqlFieldDateTime &setName(const QString &v) { VSqlField::setName(v); return *this;}
	VSqlFieldDateTime &setCreateDT(const QDateTime &v) { VSqlField::setCreateDT(v); return *this;}
	VSqlFieldDateTime &setAutor(const QString &v) { VSqlField::setAutor(v); return *this;}
	VSqlFieldDateTime &setComment(const QString &v) { VSqlField::setComment(v); return *this;}

	virtual QString sqlType() const { return QString("timestamp");}
	virtual VSqlFieldType::EType eType() const { return VSqlFieldType::EType_dateTime;}
	virtual VSqlFieldPtr clone() const;

	virtual QWidget *factoryValueEditor(QWidget *parent) const;
};

typedef QSharedPointer<VSqlFieldDateTime> VSqlFieldDateTimePtr;

///////////////////////////////////////////////////////////////////////////////

class VSqlFieldListId : public VSqlField
{
	Q_OBJECT

public:
	VSqlFieldListId &setName(const QString &v) { VSqlField::setName(v); return *this;}
	VSqlFieldListId &setCreateDT(const QDateTime &v) { VSqlField::setCreateDT(v); return *this;}
	VSqlFieldListId &setAutor(const QString &v) { VSqlField::setAutor(v); return *this;}
	VSqlFieldListId &setComment(const QString &v) { VSqlField::setComment(v); return *this;}

	VSqlFieldListId &setToTableName(const QString &v) { m_toTableName = v; return *this;}
	QString toTableName() const { return m_toTableName;}
	
	VSqlFieldListId &setToFieldName(const QString &v) { m_toFieldName = v; return *this;}
	QString toFieldName() const { return m_toFieldName;}

	virtual VSqlFieldType::EType eType() const { return VSqlFieldType::EType_listId;}
	virtual bool isRef() const { return true;}
	virtual QString sqlType() const { Q_ASSERT(false); return QString();}
	virtual VSqlFieldPtr clone() const;

	virtual void toRecord(QSqlRecord &record) const;
	virtual void fromRecord(const QSqlRecord &record);

	virtual QWidget *factoryValueEditor(QWidget *parent) const;
	
private:
	QString m_toTableName;
	QString m_toFieldName;
};

typedef QSharedPointer<VSqlFieldListId> VSqlFieldListIdPtr;

///////////////////////////////////////////////////////////////////////////////

class VSqlFieldRefId : public VSqlField
{
	Q_OBJECT

public:
	VSqlFieldRefId &setName(const QString &v) { VSqlField::setName(v); return *this;}
	VSqlFieldRefId &setCreateDT(const QDateTime &v) { VSqlField::setCreateDT(v); return *this;}
	VSqlFieldRefId &setAutor(const QString &v) { VSqlField::setAutor(v); return *this;}
	VSqlFieldRefId &setComment(const QString &v) { VSqlField::setComment(v); return *this;}

	VSqlFieldRefId &setToTableName(const QString &v) { m_toTableName = v; return *this;}
	QString toTableName() const { return m_toTableName;}

	VSqlFieldRefId &setToFieldName(const QString &v) { m_toFieldName = v; return *this;}
	QString toFieldName() const { return m_toFieldName;}

	virtual VSqlFieldType::EType eType() const { return VSqlFieldType::EType_refId;}
	virtual bool isRef() const { return true;}
	virtual QString sqlType() const { return "bigint";}
	virtual VSqlFieldPtr clone() const;

	virtual void toRecord(QSqlRecord &record) const;
	virtual void fromRecord(const QSqlRecord &record);

	virtual QWidget *factoryValueEditor(QWidget *parent) const;

private:
	QString m_toTableName;
	QString m_toFieldName;
};

typedef QSharedPointer<VSqlFieldRefId> VSqlFieldRefIdPtr;

///////////////////////////////////////////////////////////////////////////////

class VSqlFieldRefString : public VSqlField
{
	Q_OBJECT

public:
	VSqlFieldRefString() :m_maxLength(100) {}

	VSqlFieldRefString &setName(const QString &v) { VSqlField::setName(v); return *this;}
	VSqlFieldRefString &setCreateDT(const QDateTime &v) { VSqlField::setCreateDT(v); return *this;}
	VSqlFieldRefString &setAutor(const QString &v) { VSqlField::setAutor(v); return *this;}
	VSqlFieldRefString &setComment(const QString &v) { VSqlField::setComment(v); return *this;}

	VSqlFieldRefString &setToTableName(const QString &v) { m_toTableName = v; return *this;}
	QString toTableName() const { return m_toTableName;}

	VSqlFieldRefString &setToFieldName(const QString &v) { m_toFieldName = v; return *this;}
	QString toFieldName() const { return m_toFieldName;}

	VSqlFieldRefString &setMaxLength(int v) { m_maxLength = v; return *this;}
	int maxLength() const { return m_maxLength;}

	virtual VSqlFieldType::EType eType() const { return VSqlFieldType::EType_refString;}
	virtual bool isRef() const { return true;}
	virtual QString sqlType() const { return QString("varchar(%1)").arg(m_maxLength);}
	virtual VSqlFieldPtr clone() const;

	virtual void toRecord(QSqlRecord &record) const;
	virtual void fromRecord(const QSqlRecord &record);

	virtual QWidget *factoryValueEditor(QWidget *parent) const;

private:
	int m_maxLength;
	QString m_toTableName;
	QString m_toFieldName;
};

typedef QSharedPointer<VSqlFieldRefString> VSqlFieldRefStringPtr;

///////////////////////////////////////////////////////////////////////////////

#endif
